#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>


#include "proto1.h"


static key_t key;
static int msgid;

struct rcvdir_st
{
	int state;
	char * errstr;
	int fd;
	off_t offset;
	int _errno_;
};

enum
{
	STATE_P=1,
	STATE_D,
	STATE_Err,
	STATE_DOT,
	STATE_Ex,
	STATE_T
};

/*
 * 接收文件地址
 */
void rcvPath(struct rcvdir_st *rcvdir)
{
	msg_path_t msg_path;
	msg_path.mtype=MSG_PATH;
	if(msgrcv(msgid,&msg_path,sizeof(msg_path)-sizeof(long),MSG_PATH,0)<0)
	{
		rcvdir->errstr="msgrcv()";
		rcvdir->state=STATE_Err;
		rcvdir->_errno_=errno;
	}
//	msg_path.path
	printf("rcv_path==%s\n",&msg_path.path);
	fflush(NULL);
	rcvdir->state=STATE_D;
	int fd=0;
	while((fd=open(msg_path.path,O_RDONLY))<0)
	{
		if(errno!=EINTR)
		{
			rcvdir->state=STATE_Err;
			rcvdir->errstr="open()";
			rcvdir->_errno_=errno;
			break;
		}
	}
	if(fd>0)
	{
		rcvdir->fd=fd;
	}
}

/*
 *发送数据
 * */
void sndData(struct rcvdir_st *rcvdir)
{	
	union msg_s2c_un msg_s2c;
	//msg_s2c.mtype=MSG_DATA;
	msg_data_t msg_data;
	msg_data.mtype=MSG_DATA;
	msg_data.datalen=0;
	//int len=0;
	while((msg_data.datalen=read(rcvdir->fd,msg_data.data,DATASIZE)))
	{	
		if(msg_data.datalen<0)
		{
			if(errno==EINTR)
				continue;
			else
			{
				/*发送异常太*/
				rcvdir->state=STATE_Err;
				rcvdir->errstr="read()";
				rcvdir->_errno_=errno;
				break;
			}
		}
		msg_s2c.datamsg=msg_data;
		printf("len==%d\n",msg_s2c.datamsg.datalen);
		fflush(NULL);
		if(msgsnd(msgid,&msg_s2c,sizeof(msg_s2c)-sizeof(long),0)<0)
		{
			rcvdir->state=STATE_Err;
			rcvdir->errstr="msgsnd()";
			rcvdir->_errno_=errno;
			break;
		}
		printf("while end\n");
		fflush(NULL);
	}
	if(msg_data.datalen==0)
	{
		printf("STATE_Dot\n");
		fflush(NULL);
		rcvdir->state=STATE_DOT;
	}
}

/*
 *发送错误
 * */
void sndErr(struct rcvdir_st * rcvdir)
{
	rcvdir->state=STATE_P;
	union msg_s2c_un msg_s2c;
	msg_err_t msg_err;
	msg_err.mtype = MSG_ERR;
	msg_err._errno_= rcvdir->_errno_;
	msg_s2c.errmsg = msg_err;
	if(msgsnd(msgid,&msg_s2c,sizeof(msg_s2c)-sizeof(long),0)<0)
	{
		rcvdir->state = STATE_Ex;
		rcvdir->errstr = "Err msgsnd()";
		rcvdir->_errno_ = errno;
	}
}

/*
 * 发送完成处理
 * */
void sndDot(struct rcvdir_st * rcvdir)
{
	rcvdir->state = STATE_P;
	close(rcvdir->fd);
//}msg_eot_t;
	union msg_s2c_un msg_s2c;
	msg_eot_t msg_eot;
	msg_eot.mtype = MSG_EOT;
	msg_s2c.eotmsg = msg_eot;
	if(msgsnd(msgid,&msg_s2c,sizeof(msg_s2c)-sizeof(long),0)<0)
	{
		rcvdir->state = STATE_Err;
		rcvdir->errstr = "sndDOT msgsnd()";
		rcvdir->_errno_ = errno;
	}
}

void rcv_dirver(struct rcvdir_st * rcvdir)
{
	switch(rcvdir->state)
	{
		case STATE_P:
			rcvPath(rcvdir);
			break;
		case STATE_D:
			sndData(rcvdir);
			break;
		case STATE_DOT:
			sndDot(rcvdir);
			break;
		case STATE_Err:
			sndErr(rcvdir);
			break;
		case STATE_Ex:
			perror(rcvdir->errstr);
			rcvdir->state = STATE_T;
		 	break;
		case STATE_T:
			msgctl(msgid,IPC_RMID,NULL);
			exit(1);
			break;
		default:
			break;
	}
}


int main(void)
{
	struct rcvdir_st rcv;
	rcv.state=STATE_P;
	rcv.fd=-1;
	key = ftok(KEYPATH,KEYPROJ);
	if(key < 0)
	{
		rcv.errstr="ftok()";
		rcv.state=STATE_Ex;
		//perror("ftok()");
        //exit(1);
	}
	msgid = msgget(key,IPC_CREAT|0600);
	if(msgid<0)
	{
		rcv.errstr="msgget()";
		rcv.state=STATE_Ex;
	}

	while(1)
	{
		rcv_dirver(&rcv);		
	}


	exit(0);
}
